package com.seed.core.builder.search;

import cn.hutool.core.util.StrUtil;
import com.seed.core.builder.pojo.Join1;
import com.seed.core.builder.pojo.Table1;
import com.seed.core.builder.pojo.WhereCondition1;
import com.seed.core.builder.query.InBuilder;
import com.seed.core.column.Column;
import com.seed.core.enumeration.PropertyType;
import com.seed.core.enumeration.SqlOp;
import com.seed.core.pojo.seed.HasManys;
import com.seed.core.pojo.seed.Relation;
import com.seed.core.pojo.seed.Seed;
import com.seed.core.query.pojo.Searched;
import com.seed.util.Join1Kit;
import com.seed.util.SeedKit;
import com.seed.util.StrKit;

import java.util.*;

public class SearchedWrapper {

    private final List<WhereCondition1> wheres = new ArrayList<>(); // 条件对象
    private final Map<String, Join1> joins = new LinkedHashMap<>(); // 表关联对象
    private final Map<String, InBuilder> inBuilders = new LinkedHashMap<>();
    private final Map<String, Searched> fillSearcheds = new HashMap<>(); // fill对象使用

    public SearchedWrapper(Seed selfSeed, Map<String, Searched> searcheds) {
        init(null, selfSeed, searcheds);
    }

    private void init(String basePath, Seed selfSeed, Map<String, Searched> searcheds) {
        String selfTableAlias = StrKit.selfTableAlias(basePath);
//        QueryTable selfTable = new QueryTable(selfSeed.getTableName()).as(selfTableAlias);
        Table1 selfTable = new Table1(selfSeed.getTableName()).as(selfTableAlias);
        for(Map.Entry<String, Searched> entry: searcheds.entrySet()) {
            String[] items = StrKit.cutInTwo(StrKit.cutInTwo(entry.getKey(), '=', false)[0], '_', true);
            String crossOrColumn = items[0];
            String op = items[1];
            String finalPath = StrKit.concat(basePath, crossOrColumn);
            Searched value = entry.getValue();
            PropertyType propertyType = value.getType();
            switch (propertyType) {
                case none -> {
                    Column nameColumn = SeedKit.getNameColumn(selfSeed);
                    String val = value.getValue();
//                    wheres.add(ConditionUtil.condition(selfTable, nameColumn, StrUtil.isBlank(op) ? "like" : op, val));
                    SqlOp sqlOp = SqlOp.valueOf(StrUtil.isBlank(op) ? nameColumn.getDefaultOp().name() : op);
                    wheres.add(new WhereCondition1(selfTable, nameColumn.getName(), sqlOp, val));
                }
                case asterisk -> {
                    Map<String, Column> columns = selfSeed.getColumns();
                    for (Column column: columns.values()) {
                        String columName = column.getName();
                        String val = value.getValue();
//                        wheres.add(ConditionUtil.condition(selfTable, columName, SeedKit.op(selfSeed, columName).name(), val));
                        wheres.add(new WhereCondition1(selfTable, columName, column.getDefaultOp(), val));
                    }
                }
                case column -> {
                    String val = value.getValue();
                    Column column = (Column) value.getProperty();
                    op = StrUtil.isBlank(op) ? column.getDefaultOp().name() : op;
//                    wheres.add(ConditionUtil.condition(selfTable, crossOrColumn, op, val));
                    SqlOp sqlOp = StrUtil.isBlank(op) ? column.getDefaultOp() : SqlOp.valueOf(op);
                    wheres.add(new WhereCondition1(selfTable, crossOrColumn, sqlOp, val));
                }
                case hasOne, belongsTo -> {
                    Relation relation = (Relation) value.getProperty();
                    Join1 join1 = Join1Kit.buildJoin1(relation, basePath, crossOrColumn);
                    joins.putIfAbsent(finalPath, join1);
                    init(finalPath, relation.targetSeed(), value);
                }
                case hasMany, habtm -> {
                    Relation relation = (Relation) value.getProperty();
                    Seed targetSeed = relation.targetSeed();
                    inBuilders.put(finalPath, new InBuilder(selfSeed, basePath, crossOrColumn, (HasManys) relation, targetSeed, value));
                    fillSearcheds.put(finalPath, value);
                }
            }
        }
    }

    public List<WhereCondition1> getWheres() {
        return wheres;
    }

    public Map<String, Join1> getJoins() {
        return joins;
    }

    public Map<String, InBuilder> getInBuilders() {
        return inBuilders;
    }

    public Searched getFillSearched(String key) {
        return fillSearcheds.get(key);
    }

    public Map<String, Searched> getFillSearcheds() {
        return fillSearcheds;
    }
}
